/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package asis;

import asis.ini.INI;
import asis.ini.INI.IniDataFormat;
import asis.ini.INI.IniSectionHead;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import skyproc.*;
import skyproc.exceptions.BadParameter;
import skyproc.exceptions.NotFound;
import skyproc.gui.SPProgressBarPlug;

/**
 *
 * @author pc tech
 */
public class NPCPotions {

    public void addPotions() {
        internalAddPotions();
    }

    public void addPotions(ASIS a) {
        if (a.getModExclusions() != null) {
            modExclusions.addAll(a.getModExclusions());
        }
        internalAddPotions();
    }

    private void internalAddPotions() {
        SPProgressBarPlug.setStatus("NPC Potions: Starting Patch");
        SPProgressBarPlug.incrementBar();

        Mod merger = new Mod("TmpMerger", false);
        merger.addAsOverrides(SPGlobal.getDB());

        processINI();
//        try {
//            //getPatchSettings();
//            getPotionForms(merger);
//        } catch (NotFound ex) {
//            Logger.getLogger(NPCPotions.class.getName()).log(Level.SEVERE, null, ex);
//        }
        // potions are currently hard coded so no need for sublists

        hpotions = merger.getMajor("LItemPotionRestoreHealth", GRUP_TYPE.LVLI).getForm();
        mpotions = merger.getMajor("LItemPotionRestoreMagicka", GRUP_TYPE.LVLI).getForm();
        spotions = merger.getMajor("LItemPotionRestoreStamina", GRUP_TYPE.LVLI).getForm();
//        getBlockList();
        setValidNPCs(merger);
        addPotionsToNPCs(merger);
    }

    private void addPotionsToNPCs(Mod merger) {
        String scriptName = "NPCPotions";

        GLOB NPCPotionsnumItemsGLOB = (GLOB) merger.getMajor("ASISNPCPotionsnumItems", GRUP_TYPE.GLOB);
        NPCPotionsnumItemsGLOB.setValue((float) numItems);
        SPGlobal.getGlobalPatch().addRecord(NPCPotionsnumItemsGLOB);
        FormID NPCPotionsnumItems = NPCPotionsnumItemsGLOB.getForm();
        GLOB NPCPotionsnumChanceGLOB = (GLOB) merger.getMajor("ASISNPCPotionsnumChance", GRUP_TYPE.GLOB);
        NPCPotionsnumChanceGLOB.setValue((float) numChance);
        SPGlobal.getGlobalPatch().addRecord(NPCPotionsnumChanceGLOB);
        FormID NPCPotionsnumChance = NPCPotionsnumChanceGLOB.getForm();

        SPProgressBarPlug.setStatus("NPC Potions: Adding Potions");
        SPProgressBarPlug.incrementBar();
        for (NPC_ n : validNPCs) {
            try {
                ScriptRef script = new ScriptRef(scriptName);
                script.setProperty("useNPCPotions", true);
                script.setProperty("ASISNPCPotionsnumItems", NPCPotionsnumItems);
                script.setProperty("ASISNPCPotionsnumChance", NPCPotionsnumChance);
                script.setProperty("potionsList1", hpotions);
                if (n.getEDID().toUpperCase().contains("MISSILE") || n.getEDID().toUpperCase().contains("MELEE")) {
                    script.setProperty("potionsList2", spotions);
                } else {
                    script.setProperty("potionsList2", mpotions);
                }
                n.getScriptPackage().addScript(script);

                /*
                 * if (n.getEDID().toUpperCase().contains("MISSILE") ||
                 * n.getEDID().toUpperCase().contains("MELEE")) { n.addItem(hsplist.getForm(),
                 * 1); } else { n.addItem(hmplist.getForm(), 1); }
                 */
                SPGlobal.getGlobalPatch().addRecord(n);
            } catch (Exception e) {
                SPGlobal.logException(e);
            }

        }
    }

    private void processINI() {

        SPProgressBarPlug.setStatus("NPC Potions: Processing INI");
        SPProgressBarPlug.incrementBar();
        INI ini = null;

        try {
            ini = new INI("NPCPotions.ini");
        } catch (IOException ex) {
            Logger.getLogger(NPCPotions.class.getName()).log(Level.SEVERE, null, ex);
        }

        Collection<INI.IniSectionHead> sections = getSectionList();

        ini.addSection(sections);

        try {
            ini.readData();
        } catch (IOException ex) {
            Logger.getLogger(NPCPotions.class.getName()).log(Level.SEVERE, null, ex);
        }

        initializeLists(ini);
    }

    private Collection<INI.IniSectionHead> getSectionList() {
        Collection<INI.IniSectionHead> sectionList = new ArrayList<>();

        for (IniSection currentSection : IniSection.values()) {
            sectionList.add(new INI.IniSectionHead(currentSection.getName(), currentSection.getFormat()));
        }

        return sectionList;
    }

    private void setValidNPCs(Mod merger) {
        validNPCs = new LinkedHashSet<>(merger.getNPCs().getRecords());

        //Clean-up NPC's from excluded mods.  This is done as blocking the import 
        // could cause previous NPC's to override an excluded mods NPC's.

        Mod tempMod;

        for (String list : modExclusions) {
            try {
                tempMod = SPDatabase.getMod(new ModListing(list));
                validNPCs.removeAll(tempMod.getNPCs().getRecords());
            } catch (Exception e) {
                //Do nothing, probably doesn't have the mod in the exclusions.
            }
        }

        ArrayList<NPC_> badNPCs = new ArrayList<>();
        for (NPC_ n : validNPCs) {
            if (!getValidNPC(n)) {
                badNPCs.add(n);
            }
        }
        for (NPC_ n : badNPCs) {
            validNPCs.remove(n);
        }
    }

    private boolean getValidNPC(NPC_ n) {
        boolean include = false;
        boolean exclude = false;
        String list;
        String edid = n.getEDID().toUpperCase();

        if (n.get(MajorRecord.MajorFlags.Deleted)) {
            return false;
        }
        if (n.isTemplated() && n.get(NPC_.TemplateFlag.USE_SCRIPTS)) {
            return false;
        }


        if (inclusions.isEmpty()) {
            include = true;
        } else {
            for (int i = 0; i < inclusions.size(); i++) {
                list = ((String) inclusions.get(i)).toUpperCase();
                if (edid.contains(list)) {
                    include = true;
                    break;
                }
            }
        }
        if (include && !exclusions.isEmpty()) {
            for (int i = 0; i < exclusions.size(); i++) {
                list = ((String) exclusions.get(i)).toUpperCase();
                if (edid.contains(list)) {
                    exclude = true;
                    break;
                }
            }
        }

        return (include && !exclude);
    }

    private void getPotionForms(Mod merger) throws NotFound {
        LVLI hplist = new LVLI("ASISLVLHEALTHPOTIONS");
        hpotions = hplist.getForm();
        LVLI mplist = new LVLI("ASISLVLMAGICPOTIONS");
        mpotions = mplist.getForm();
        LVLI splist = new LVLI("ASISLVLSTAMINAPOTIONS");
        spotions = splist.getForm();
        /*
         * hmplist = new LVLI(SPGlobal.getGlobalPatch(), "ASISLVLHMPOTIONS"); hsplist = new
         * LVLI(SPGlobal.getGlobalPatch(), "ASISLVLHSPOTIONS");
         */
        for (LVLI li : merger.getLeveledItems()) {
            switch (li.getEDID().toUpperCase()) {
                case "LITEMPOTIONRESTOREHEALTH":
                    hplist.addEntry(li.getForm(), 1, 1);
                    break;
                case "LITEMPOTIONRESTOREMAGICKA":
                    mplist.addEntry(li.getForm(), 1, 1);
                    break;
                case "LITEMPOTIONRESTORESTAMINA":
                    splist.addEntry(li.getForm(), 1, 1);
                    break;
            }
        }
        try {
            hplist.setChanceNone(0);
        } catch (BadParameter ex) {
            Logger.getLogger(NPCPotions.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {
            mplist.setChanceNone(0);
        } catch (BadParameter ex) {
            Logger.getLogger(NPCPotions.class.getName()).log(Level.SEVERE, null, ex);
        }
        try {
            splist.setChanceNone(0);
        } catch (BadParameter ex) {
            Logger.getLogger(NPCPotions.class.getName()).log(Level.SEVERE, null, ex);
        }

        hplist.set(LeveledRecord.LVLFlag.CalcForEachItemInCount, true);
        splist.set(LeveledRecord.LVLFlag.CalcForEachItemInCount, true);
        mplist.set(LeveledRecord.LVLFlag.CalcForEachItemInCount, true);

        hplist.set(LeveledRecord.LVLFlag.CalcAllLevelsEqualOrBelowPC, true);
        splist.set(LeveledRecord.LVLFlag.CalcAllLevelsEqualOrBelowPC, true);
        mplist.set(LeveledRecord.LVLFlag.CalcAllLevelsEqualOrBelowPC, true);
        /*
         * hmplist.set(LeveledRecord.LVLFlag.UseAll, true);
         * hmplist.set(LeveledRecord.LVLFlag.CalcAllLevelsEqualOrBelowPC, false);
         * hmplist.set(LeveledRecord.LVLFlag.CalcForEachItemInCount, false);
         * hsplist.set(LeveledRecord.LVLFlag.UseAll, true);
         * hsplist.set(LeveledRecord.LVLFlag.CalcAllLevelsEqualOrBelowPC, false);
         * hsplist.set(LeveledRecord.LVLFlag.CalcForEachItemInCount, false); try {
         * hmplist.setChanceNone(numChance); } catch (BadParameter ex) {
         * Logger.getLogger(NPCPotions.class.getName()).log(Level.SEVERE, null, ex); } try {
         * hsplist.setChanceNone(numChance); } catch (BadParameter ex) {
         * Logger.getLogger(NPCPotions.class.getName()).log(Level.SEVERE, null, ex); }
         *
         * hmplist.addEntry(hplist.getForm(), 1, 1); hmplist.addEntry(mplist.getForm(), 1, 1);
         *
         * hsplist.addEntry(hplist.getForm(), 1, 1); hsplist.addEntry(splist.getForm(), 1, 1);
         */
        SPGlobal.getGlobalPatch().addRecord(hplist);
        SPGlobal.getGlobalPatch().addRecord(mplist);
        SPGlobal.getGlobalPatch().addRecord(splist);
        //SPGlobal.getGlobalPatch().addRecord(hmplist);
        //SPGlobal.getGlobalPatch().addRecord(hsplist);
    }

    private void getBlockList() {
        //Clean-up NPC's from excluded mods.  This is done as blocking the import 
        // could cause previous NPC's to override an excluded mods NPC's.
        String list;
        Mod tempMod;
        for (int i = 0; i < modExclusions.size(); i++) {
            list = (String) modExclusions.get(i);
            try {
                tempMod = SPDatabase.getMod(new ModListing(list));
                for (NPC_ n : tempMod.getNPCs()) {
                    npcBlockList.add(n.getForm());
                }
            } catch (Exception e) {
                //Do nothing, probably doesn't have the mod in the exclusions.
            }
        }
    }

    private void initializeLists(INI ini) {
        inclusions = (ArrayList) ini.getCollection(new IniSectionHead(IniSection.NPCINCLUSIONS.getName(),
                IniSection.NPCINCLUSIONS.getFormat()));
        exclusions = (ArrayList) ini.getCollection(new IniSectionHead(IniSection.NPCEXCLUSIONS.getName(),
                IniSection.NPCEXCLUSIONS.getFormat()));
        modExclusions.addAll((ArrayList) ini.getCollection(new IniSectionHead(IniSection.MODEXCLUSIONS.getName(),
                IniSection.MODEXCLUSIONS.getFormat())));

        numItems = ASIS.save.getInt(ASISSaveFile.GUISettings.NUMBER_OF_POTIONS);
        numChance = ASIS.save.getInt(ASISSaveFile.GUISettings.CHANCE_PER_POTION);
    }

    private enum IniSection {

        PATCHSETTINGS(IniDataFormat.KEY_VALUE, "PATCHSETTINGS"),
        NPCINCLUSIONS(IniDataFormat.VALUE, "NPCINCLUSIONS"),
        NPCEXCLUSIONS(IniDataFormat.VALUE, "NPCEXCLUSIONS"),
        MODEXCLUSIONS(IniDataFormat.VALUE, "MODEXCLUSIONS");
        private IniDataFormat format;
        private String name;

        IniSection(IniDataFormat format, String name) {
            this.format = format;
            this.name = name;
        }

        String getName() {
            return name;
        }

        IniDataFormat getFormat() {
            return format;
        }
    }
    String settingType = null;
    String settingValue = null;
    ArrayList inclusions = new ArrayList<>(0);
    ArrayList exclusions = new ArrayList<>(0);
    ArrayList<String> modExclusions = new ArrayList<>(0);
    ArrayList<FormID> npcBlockList = new ArrayList<>();
    static int numProgressSections = 4;
    INI npcPotions;
    FormID hpotions;
    FormID mpotions;
    FormID spotions;
    int numChance;
    int numItems;
    LVLI hmplist;
    LVLI hsplist;
    private Set<NPC_> validNPCs;
}